import Meals from './components/Meals/Meals.js';
import FilterMeals from './components/FilterMeals/FilterMeals.js';
import Cart from './components/Cart/Cart.js';

import Big from 'big.js';

import CartContext from './store/cart-context.js';

import { useState, useReducer, useCallback } from 'react';


const MEALS_DATA = [
  {
    id: 1,
    title: 'Burger',
    imgUrl: '/img/meals/hamburger.png',
    desc: 'A classic burger with a tomato sauce and lettuce',
    price: 12.99,
  },
  {
    id: 2,
    title: 'Fries',
    imgUrl: '/img/meals/fries.png',
    desc: 'Crispy fries with garlic and cheese',
    price: 7.99,
  },
  {
    id: 3,
    title: 'Pizza',
    imgUrl: '/img/meals/pizza.png',
    desc: 'A delicious pizza with tomato sauce and cheese',
    price: 15.99,
  },
  {
    id: 4,
    title: 'Sushi',
    imgUrl: '/img/meals/sushi.png',
    desc: 'A classic sushi with fresh seafood',
    price: 10.99,
  },
  {
    id: 5,
    title: 'Burrito',
    imgUrl: '/img/meals/burrito.png',
    desc: 'A delicious burrito with beans, rice, and guacamole',
    price: 12.99,
  },
  {
    id: 6,
    title: 'Tacos',
    imgUrl: '/img/meals/tacos.png',
    desc: 'A delicious taco with beans, rice, and guacamole',
    price: 10.99,
  }

]

/* 
    args: 
    reducer: a function that takes two arguments:
      state: the current state of the reducer
      action: an object with a type property and optionally a payload property
    initialState: the initial state of the reducer

  returns: 
    array: 
      [0]: the current state of the reducer
      [1]: dispatch function that can be used to trigger actions on the reducer

*/


// advoiding repeat code
const cartReducer = (state, action) => {
  const newCart = { ...state };

  switch (action.type) {
    case 'ADD_ITEM':
      if (newCart.items.indexOf(action.meal) === -1) {
        newCart.items.push(action.meal);
        action.meal.amount = 1;
      } else {
        // if meal is already in cart, increment the amount
        action.meal.amount += 1;
      }
      newCart.totalAmount++;
      // newCart.totalPrice += meal.price;
      newCart.totalPrice = new Big(newCart.totalPrice).plus(new Big(action.meal.price)).toNumber();

      return newCart;
    case 'REMOVE_ITEM':
      action.meal.amount -= 1;
      if (action.meal.amount === 0) {
        newCart.items.splice(newCart.items.indexOf(action.meal), 1);
      }
      newCart.totalAmount--;
      newCart.totalPrice = new Big(newCart.totalPrice).minus(new Big(action.meal.price)).toNumber();
      return newCart;
    case 'CLEAR_CART':
      newCart.items.forEach(item => delete item.amount)
      newCart.items = [];
      newCart.totalAmount = 0;
      newCart.totalPrice = 0;
      return newCart;
    default:
      return state;
  }
}


function App() {
  // mealsData is the state variable that holds the meals data
  const [mealsData, setMealsData] = useState(MEALS_DATA);

  const [cartData, cartDispatch] = useReducer(cartReducer, {
    items: [],
    totalAmount: 0,
    totalPrice: 0
  });


  /* 
  useCallback: 
    args: 
      1.callback function to be memoized

      2.optional array of dependencies to be used for memoization
        - when array of dependencies changes, the memoized callback function will be recalculated
        - if no dependencies are provided, the callback function will be recalculated every time the component renders
        - all used args and props should be included in the dependencies array to avoid unnecessary recalculations
   */

  // filterHandler is the function that filters the meals data based on the keyword
  const filterHandler = useCallback((keyword) => {
    const newMealsData = MEALS_DATA.filter(item => item.title.toLowerCase().indexOf(keyword.toLowerCase()) !== -1);
    setMealsData(newMealsData);
  }, [])


  return (
    <CartContext.Provider value={{ ...cartData, cartDispatch }}>
      <div style={{ width: '750rem', height: '400px' }}>

        <FilterMeals
          onfilter={filterHandler}
        />

        <Meals
          mealsData={mealsData}
        />

        <Cart />
      </div>
    </CartContext.Provider>
  );
}

export default App;
